
namespace Needle.Utils {
    /// <summary>
    /// Utils used in debugging.
    /// </summary>
    public class DebugUtils {

        ///// <summary>
        ///// Creates and save an assembly containing a hardcoded activator for every EmitActivator passed in.
        ///// </summary>
        //public static void SaveAssembly(string assemblyName, IEnumerable<Compiled.EmitActivator> activators) {
        //    AssemblyName asmName = new AssemblyName();
        //    asmName.Name = assemblyName;

        //    Debug.WriteLine("Saving " + asmName.Name + ".dll...");

        //    AppDomain appDom = AppDomain.CurrentDomain;
        //    AssemblyBuilder asmBuilder = appDom.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
        //    ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(asmName.Name, asmName.Name + ".obj", true);

        //    // Define activators.
        //    foreach (Compiled.EmitActivator activator in activators) {
        //        CreateActivatorType(modBuilder, activator);
        //    }

        //    asmBuilder.Save(asmName.Name + ".dll");
        //}

        //private static void CreateActivatorType(ModuleBuilder modBuilder, Compiled.EmitActivator activator) {
        //    InstanceId id = activator.Id;
        //    string typeName = ToSafeName(ref id);
        //    TypeBuilder type = modBuilder.DefineType("Activators." + typeName + "_Activator", TypeAttributes.Public | TypeAttributes.Class, typeof(ActivatorBase));
        //    FieldBuilder actSeqField = BuildActivationSequenceField(type, activator);
        //    BuildActivationSequenceProperty(type, actSeqField, activator);
        //    BuildConstructor(type, actSeqField, activator);
        //    MethodInfo createInstance = BuildCreateInstanceWithKernelMethod(type, activator);
        //    BuildCreateInstanceMethod(type, createInstance);
        //    type.CreateType();

        //}

        //private static string ToSafeName(ref InstanceId id) {
        //    return Regex.Replace(id.ToString(), @"[^\w]", "_");
        //}

        //private static void BuildConstructor(TypeBuilder type, FieldBuilder actSeqField, Compiled.EmitActivator activator) {

        //    // Preparing Reflection instances
        //    MethodInfo getTypeFromHandle = typeof(Type).GetMethod(
        //        "GetTypeFromHandle",
        //        BindingFlags.Static
        //        | BindingFlags.Public
        //        | BindingFlags.NonPublic,
        //        null,
        //        new Type[] { typeof(RuntimeTypeHandle) },
        //        null
        //        );
        //    ConstructorInfo dependencyIdCtor = typeof(InstanceId).GetConstructor(
        //        BindingFlags.Instance
        //        | BindingFlags.Public
        //        | BindingFlags.NonPublic,
        //        null,
        //        new Type[] { typeof(Type), typeof(String) },
        //        null
        //        );
        //    ConstructorInfo activatorBaseCtor = typeof(ActivatorBase).GetConstructor(
        //        BindingFlags.Instance
        //        | BindingFlags.Public
        //        | BindingFlags.NonPublic,
        //        null,
        //        new Type[] { typeof(InstanceId), typeof(Type), typeof(bool) },
        //        null
        //        );
        //    ConstructorInfo reflectionActivationInfoCtor = typeof(ReflectionActivationInfo).GetConstructor(
        //        BindingFlags.Instance
        //        | BindingFlags.Public
        //        | BindingFlags.NonPublic,
        //        null,
        //        new Type[] { typeof(InstanceId), typeof(Type) },
        //        null
        //        );
        //    ConstructorInfo activationSequenceCtor = activator.ActivationSequence.GetType().GetConstructor(
        //        BindingFlags.Instance
        //        | BindingFlags.Public
        //        | BindingFlags.NonPublic,
        //        null,
        //        new Type[] { typeof(InstanceId), typeof(object), typeof(IActivationInfo) },
        //        null
        //        );

        //    // Generate constructor
        //    ConstructorBuilder ctor = type.DefineConstructor(
        //        MethodAttributes.Public
        //        | MethodAttributes.HideBySig,
        //        CallingConventions.Standard,
        //        Type.EmptyTypes);

        //    // Writing body
        //    ILGenerator gen = ctor.GetILGenerator();
        //    // Preparing locals
        //    LocalBuilder id = gen.DeclareLocal(typeof(InstanceId));
        //    LocalBuilder info = gen.DeclareLocal(typeof(IActivationInfo));
        //    // load 'this' for base constructor
        //    gen.Emit(OpCodes.Ldarg_0);
        //    //load new dependency id for base constuctor
        //    gen.Emit(OpCodes.Ldtoken, activator.Id.Type);
        //    gen.Emit(OpCodes.Call, getTypeFromHandle);
        //    if (activator.Id.IsNamed) {
        //        gen.Emit(OpCodes.Ldstr, activator.Id.Name);
        //    } else {
        //        gen.Emit(OpCodes.Ldnull);
        //    }
        //    gen.Emit(OpCodes.Newobj, dependencyIdCtor);
        //    // load activated type
        //    gen.Emit(OpCodes.Ldtoken, activator.ActivatedType);
        //    gen.Emit(OpCodes.Call, getTypeFromHandle);
        //    //if (activator.EventsEnabled) {
        //    //    gen.Emit(OpCodes.Ldc_I4_1);
        //    //} else {
        //    //    gen.Emit(OpCodes.Ldc_I4_0);
        //    //}
        //    // call base constructor
        //    gen.Emit(OpCodes.Call, activatorBaseCtor);

        //    //create and store local var id
        //    gen.Emit(OpCodes.Ldtoken, activator.Id.Type);
        //    gen.Emit(OpCodes.Call, getTypeFromHandle);
        //    if (activator.Id.IsNamed) {
        //        gen.Emit(OpCodes.Ldstr, activator.Id.Name);
        //    } else {
        //        gen.Emit(OpCodes.Ldnull);
        //    }
        //    gen.Emit(OpCodes.Newobj, dependencyIdCtor);
        //    gen.Emit(OpCodes.Stloc, id);

        //    // create and store local var info
        //    gen.Emit(OpCodes.Ldloc, id);
        //    gen.Emit(OpCodes.Ldtoken, activator.ActivatedType);
        //    gen.Emit(OpCodes.Call, getTypeFromHandle);
        //    gen.Emit(OpCodes.Newobj, reflectionActivationInfoCtor);
        //    gen.Emit(OpCodes.Stloc, info);

        //    //load this for field access later on
        //    gen.Emit(OpCodes.Ldarg_0);
        //    // construct and store activation sequence
        //    gen.Emit(OpCodes.Ldloc, id); // id
        //    gen.Emit(OpCodes.Ldarg_0);// this
        //    gen.Emit(OpCodes.Ldloc, info);// activation info
        //    gen.Emit(OpCodes.Newobj, activationSequenceCtor);
        //    gen.Emit(OpCodes.Stfld, actSeqField);

        //    // finished
        //    gen.Emit(OpCodes.Ret);
        //}

        //private static void BuildActivationSequenceProperty(TypeBuilder type, FieldBuilder backingField, Compiled.EmitActivator activator) {
        //    // Declaring getter method
        //    MethodBuilder get_ActivationSequence = type.DefineMethod(
        //        "get_ActivationSequence",
        //        MethodAttributes.Public
        //        | MethodAttributes.Virtual
        //        | MethodAttributes.HideBySig
        //        | MethodAttributes.SpecialName,
        //        typeof(object),
        //        Type.EmptyTypes
        //        );
        //    // Writing body
        //    ILGenerator gen = get_ActivationSequence.GetILGenerator();
        //    gen.Emit(OpCodes.Ldarg_0);
        //    gen.Emit(OpCodes.Ldfld, backingField);
        //    // finished
        //    gen.Emit(OpCodes.Ret);

        //    // Declaring property
        //    PropertyBuilder activationSequence = type.DefineProperty(
        //        "ActivationSequence",
        //        PropertyAttributes.None,
        //        typeof(object),
        //        Type.EmptyTypes
        //        );
        //    activationSequence.SetGetMethod(get_ActivationSequence);
        //}

        //private static FieldBuilder BuildActivationSequenceField(TypeBuilder type, Compiled.EmitActivator activator) {
        //    FieldBuilder field = type.DefineField(
        //       "m_ActivationSequence",
        //       activator.ActivationSequence.GetType(),
        //       FieldAttributes.Private
        //       );
        //    return field;
        //}

        //private static MethodBuilder BuildCreateInstanceWithKernelMethod(TypeBuilder type, Compiled.EmitActivator activator) {

        //    // Declaring method builder
        //    MethodBuilder createInstance = type.DefineMethod(
        //        "CreateInstance",
        //        MethodAttributes.Family
        //        | MethodAttributes.HideBySig,
        //        typeof(Object),
        //        new Type[] { typeof(IKernel) });
        //    // Parameter kernel
        //    ParameterBuilder kernel = createInstance.DefineParameter(1, ParameterAttributes.None, "kernel");
        //    // Get the activation sequence
        //    Compiled.ActivationSequence activationSequence;
        //    activationSequence = (Compiled.ActivationSequence)activator.ActivationSequence;
        //    // Writing body
        //    ILGenerator gen = createInstance.GetILGenerator();
        //    activationSequence.EmitBody(gen, true);
        //    // finished
        //    return createInstance;
        //}

        //private static void BuildCreateInstanceMethod(TypeBuilder type, MethodInfo createInstanceWithKernel) {
        //    // Preparing Reflection instances
        //    MethodInfo getKernel = typeof(ActivatorBase).GetMethod(
        //        "GetKernel",
        //        BindingFlags.Instance
        //        | BindingFlags.Public
        //        | BindingFlags.NonPublic,
        //        null,
        //        Type.EmptyTypes,
        //        null
        //        );
        //    // Declaring method builder
        //    MethodBuilder createInstance = type.DefineMethod(
        //        "CreateInstance",
        //        MethodAttributes.Public
        //        | MethodAttributes.Virtual
        //        | MethodAttributes.HideBySig,
        //        typeof(Object),
        //        Type.EmptyTypes
        //        );
        //    // Writing body
        //    ILGenerator gen = createInstance.GetILGenerator();
        //    // Preparing locals
        //    LocalBuilder k = gen.DeclareLocal(typeof(IKernel));
        //    gen.Emit(OpCodes.Ldarg_0);
        //    gen.Emit(OpCodes.Call, getKernel);
        //    gen.Emit(OpCodes.Stloc_0);
        //    gen.Emit(OpCodes.Ldarg_0);
        //    gen.Emit(OpCodes.Ldloc_0);
        //    gen.Emit(OpCodes.Call, createInstanceWithKernel);
        //    // finished
        //    gen.Emit(OpCodes.Ret);
        //}

    }

}
